<!--
 Login.vue 这种是单文件组件
 单文件组件由三部分组成：template（模板）  script（行为）  style（样式）
 -->

<template>
  <div class="login-container">
    <div class="login_box">
      <!-- 头像区域 -->
      <div class="avatar_box">
        <img
          src="../assets/logo.png"
          alt
        />
      </div>
      <!-- 登录表单区域 -->
      <!-- 需要使用elemetUI，那就要在plugins文件中的element.js中先引入组件名 -->
      <!-- :model是v-bind:model的缩写 只是将父组件的数据传递到了子组件 和 v-model不是一个东西 -->
      <!-- ref="loginFormRef" ref用于获取整个表单实例对象 -->
      <el-form
        class="login_form"
        :model="loginForm"
        :rules="loginFormRules"
        ref="loginFormRef"
      >
        <!-- 用户名 -->
        <!-- prop="username" 通过prop指定对应的验证规则 -->
        <el-form-item prop="username">
          <!-- v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定 -->
          <!-- 在main.js中已经引入了 阿里图标库 所以可以使用阿里的图标，因为elementUI的图标太少了 -->
          <el-input
            v-model="loginForm.username"
            prefix-icon="iconfont icon-user"
          ></el-input>
        </el-form-item>
        <!-- 密码 -->
        <el-form-item prop="password">
          <!-- type="password" 表示这个input输入框是密码框，会隐藏输入的值 -->
          <el-input
            v-model="loginForm.password"
            prefix-icon="iconfont icon-3702mima"
            type="password"
          ></el-input>
        </el-form-item>
        <!-- 按钮 -->
        <el-form-item class="formBtns">
          <el-button
            type="primary"
            @click="login"
          >登录</el-button>
          <el-button
            type="info"
            @click="resetLoginForm"
          >重置</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
// export default是ES6的语法，意思是将这个东西导出
// 类似于把这个封装成一个类，给其他的import引入
export default {

  data () {
    return {
      // 这是登录表单的数据对象
      loginForm: {
        username: '',
        password: ''
      },
      // 表单的input输入验证规则
      loginFormRules: {
        // 验证用户名是否合法
        username: [
          // required: true--->必填项   trigger: 'blur' 验证的时机是鼠标失去焦点的时候
          { required: true, message: '请输入登录名称', trigger: 'blur' },
          // 第二条验证 ，长度最小3位，最大5位
          { min: 3, max: 8, message: '用户名长度位3-8位', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { min: 6, max: 12, message: '密码长度为6-12位', trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    // 重置登录表单数据函数
    // resetLoginForm: function (){}  === resetLoginForm (){}
    resetLoginForm: function () {
      // this.$refs.loginFormRef 就是获取到属性名称为ref 叫做loginFormRef的表单，然后调用它的resetFields()方法重置表单
      this.$refs.loginFormRef.resetFields()
    },
    // 登录按钮-提交表单数据函数
    login () {
      /*
       validate()是elemetUI的自带表单预验证方法，
       参数为一个回调函数，回调函数里的值第一个是表示验证是否成功，
       返回的valid值是false表示表单验证失败，true表示验证成功，
       第二个是返回验证失败的数据，那个验证失败，返回那个数据提示
      */
      // ? 进行表单提交预验证函数
      this.$refs.loginFormRef.validate(async (valid, err) => {
        // console.log(valid)
        // console.log(err)
        // !如果预验证返回的值是false表示验证失败，直接return，结束提交操作，不进行表单提交
        // !Eslint的格式化直接隐藏了单个return，所以要写成return false才不会被格式化隐藏
        if (!valid) { return false }
        // !通过async await来见过promise数据的操作
        // const result = await this.$axios.post('login', this.loginForm)
        // console.log(result)
        // !当返回的数据类型是Promise的时候，可以用 async await 来简化数据操作,直接获得返回数据中的data部分
        // !(注意：data部分中还分有data和其他数据，若只需要data部分中的data数据，则可用{data:res}进行结构赋值，将data部分中的data赋值给res)
        // !同时，await只能由async来修饰，所以要将await紧挨着的那个方法用async来修饰

        // ? 通过{data:res}结构赋值出data部分中的data，赋值给res保存
        // ! 如果通过const保存axios函数，那axios中就不能用.then函数，否则回报错
        const { data: res } = await this.$axios.post('login', this.loginForm)
        // console.log(res)

        // msg弹窗
        // 如果res中的status状态码不是200，则表示登录失败,反之，则登录成功
        if (res.meta.status !== 200) {
          return this.$message({
            // 是否显示msg的关闭按钮
            showClose: true,
            message: '登录失败',
            type: 'error'
          })
        } else {
          /**
           *!将登录成功后的data中的一个token数据保存下来，因为当项目中除了登录页面之外的API接口，
           *!必须在登录之后才能进行访问，这个token就像一个权限卡一样
           *!token 之应该在当前网站打开期间生效，所以保存在客户端控制台Application中的Session Storage中
        */
          console.log(res)
          // 这里将数据中的token保存到sessionStorage中去，名字叫做token
          // window.sessionStorage.setItem('token', res.data.token)
          window.sessionStorage.setItem('token', res.data.token)
          // 同时，也保存一个当前登录用户的ID，用于 欢迎回来：用户名 （个人中心）查找用户使用
          window.sessionStorage.setItem('currentUserId', res.data.id)
          // 获取数据后进行路由跳转，转到/home页面
          this.$router.push('/home')

          // elementUI的msg弹窗
          // this.$message.success('成功消息')
          return this.$message({
            // 是否显示msg的关闭按钮
            showClose: true,
            // 获取返回数据中的msg提示
            message: res.meta.msg,
            type: 'success'
          })
        }

        /**  测试用的一般axios使用方法
         * ! login登录应该是用post，且通过data中的loginForm双向绑定的数据传参，但是我本地测试，就用get了
         *  this.$axios.get('/json/login.json').then((res) => {
          // ! 注意，axios中的then()必须用ES6语法：（res）=>{},否则会出现this指向错乱
          // ! function (err){} 这个就是ES5的，会造成this指向错乱
              this.$message.success('成功消息')
            }).catch((err) => {
                console.log(err)
                this.$message({
                // 是否显示msg的关闭按钮
                showClose: true,
                message: '错误信息',
                type: 'error'
              })
            })
         */
      })
    }
  }
}

</script>

<!--
lang="stylus" 表示这个节点中支持stylus语法格式
scoped 表示这里的style样式只对这个组件内生效，不会影响到其他组件，这也是必须的要求
 -->
<style lang="less" scoped>
.login-container {
  background-image: url("../assets/backgroundImg.jpg");
  background-repeat: no-repeat;
  background-size: 100%;
  height: 100%;
}
.login_box {
  width: 450px;
  height: 300px;
  background-color: #fff;
  border-radius: 30px;
  // 通过绝对定位进行设置位置
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  // 也可以通过在父元素上添加display:flex进行内容居中

  // 头像区域
  // less css样式嵌套
  .avatar_box {
    height: 130px;
    width: 130px;
    border: 1px solid #eeee;
    border-radius: 50%;
    padding: 10px;
    box-shadow: 0 0 10px #dddd;
    position: absolute;
    left:50%;
    // 第一个-50%是水平轴向左平移50% 第二个-50%是y轴的
    transform:translate(-50%,-50%);
    // 因为上半圈超出去了，所以设置一个背景色好看点
    background:#fff;
    img {
      width: 100%;
      height: 100%;
      border-radius: 50%;
      background: #eeee;
    }
  }
}
// login的输入框
.login_form {
  position: absolute;
  bottom: 0;
  width: 100%;
  padding: 0 20px;
  // 如果不设置盒模型，那么会因为padding而向右偏移
  box-sizing: border-box;
}
.formBtns{
  display:flex;
  justify-content: flex-end;
}
</style>
